﻿using System;
using System.Runtime.CompilerServices;
using System.Xml.Linq;

namespace ClassLibrary1
{
    public class LawOfDemeterClass
    {
        public class DataObject
        {
            public string Name { get; set; }
            public int Value { get; set; }
            public int Something { get; set; }
            public int AnotherValue { get; set; }
            public DataObject Parent { get; set; }
        }

        public class ClassObject
        {
            public void Foo()
            {
                Console.WriteLine("Foo");
            }

            public void Bar()
            {
                Console.WriteLine("Bar");
            }

            public void DoSomething(object node)
            {
                Console.WriteLine("cool" + node);
            }

            public ClassObject ReturnSelf()
            {
                return this;
            }

            public DataObject Value { get; set; }

            public DataObject ValueField;
        }

        public void ConcatenationOfClasses(XElement xElement)
        {
            var name = xElement.Attributes().GetEnumerator().GetType().Name;
            Console.WriteLine(name);
        }

        [CompilerGenerated]
        public void GeneratedCode(XElement xElement)
        {
            var name = xElement.Attributes().GetEnumerator().GetType().Name;
            Console.WriteLine(name);
        }

        public void CastInstructions(XNode xNode)
        {
            var firstNode = ((XElement)((XElement)xNode).FirstNode).FirstNode;
            Console.WriteLine(firstNode);
        }

        public void ConcatenateCallsToSelf()
        {
            var self = ReturnSelf().ReturnSelf().ReturnSelf();
            Console.WriteLine(self);
        }

        public void PassingAsParameter(XNode xNode)
        {
            Console.WriteLine(xNode);
            Console.WriteLine(xNode);
            Console.WriteLine(xNode);
        }

        public void PassingCallAsParameter(XNode xNode, ClassObject value)
        {
            value.DoSomething(xNode.Parent);
        }

        public void CallToField(ClassObject value)
        {
            var valueField = value.ReturnSelf().ValueField;
            Console.WriteLine(valueField);
        }

        public void MembersOfCommonTypes(XNode xNode)
        {
            var length = xNode.ToString().ToLower().ToUpperInvariant().Length;
            Console.WriteLine(length);
        }

        public void ConsecutiveCalls(Class2 value)
        {
            value.Wroom();
            value.Wroom();
            value.Wroom();
        }

        public void ConcatenationWithParameters(XElement xNode)
        {
            var xElement = xNode.Element("hello").Element("world");
            Console.WriteLine(xElement);
        }

        public void CallDataObjects(DataObject value)
        {
            var parent = value.Parent.Parent.Parent;
            Console.WriteLine(parent);
        }

        public void CallClassThenDataObjects(ClassObject value)
        {
            var parent = value.Value.Parent.Parent;
            Console.WriteLine(parent);
        }

        public LawOfDemeterClass ReturnSelf()
        {
            Console.WriteLine("self");
            return this;
        }
    }
}
